package model

import (
    "fmt"
    "strings"

    "git.inspur.com/x/models"

    "git.inspur.com/x/iam-adapter-go/resource"
)

type Layer struct {
    Id          string      `xorm:"pk" json:"versionId" valid:"-" `
    Name        string      `json:"layerName" valid:"-"`
    Creator     string      `json:"creator" valid:"-"`
    A5tId       string      `xorm:"account_id" json:"accountId" valid:"-"`
    CreatorName string      `json:"creatorName" valid:"-"`
    A5tName     string      `xorm:"account_name" json:"accountName" valid:"-"`
    RootId      string      `json:"layerId" valid:"-"`
    Version     string      `json:"version" valid:"-"`
    Runtimes    []string    `json:"runtimes" valid:"runtimes~函数运行时不支持" xorm:"json"`
    Description string      `json:"description" valid:"-"`
    RegionCode  string      `json:"regionCode" valid:"-" `
    RegionName  string      `json:"regionName" valid:"-" `
    Priority    int         `json:"priority" valid:"-" xorm:"-"`
    CreateTime  models.Time `xorm:"created" json:"createTime" valid:"-" `
    UpdateTime  models.Time `xorm:"updated" json:"updateTime" valid:"-" `
    DeleteTime  models.Time `xorm:"deleted" json:"deleteTime" valid:"-" `
}

type LayerVersionList struct {
    LayerId    string      `json:"layerId"`
    LayerName  string      `json:"layerName"`
    Versions   []*Layer    `json:"versions"`
    UpdateTime models.Time `xorm:"updated" json:"updateTime" valid:"-" `
}

func CreateLayer(layer *Layer) (*Layer, error) {
    if _, err := models.Engine.Insert(layer); err != nil {
        _ = logger.Error("CreateLayer: insert error: %v", err)
        return nil, err
    }
    return layer, nil
}

func CheckLayerExist(uid, name string) (bool, error) {
    l := &Layer{}
    return models.Engine.Where("creator=?", uid).And("name=?", name).Exist(l)
}

func GetLayerByUserAndLayerId(user *resource.User, id string) (*Layer, error) {
    l := &Layer{}
    has, err := models.Engine.Where("creator=?", user.Id).And("id=?", id).Get(l)
    if err != nil {
        _ = logger.Error("GetLayerByUserAndLayerId err : ", err)
        return nil, InternalServerError(LayerGetError, err.Error())
    }
    if !has {
        _ = logger.Warn("GetLayerByUserAndLayerId: did not find layer info, id=%v, userId=%v", id, user.Id)
        return nil, InternalServerError(LayerGetError, "没有找到层数据")
    }
    return l, nil
}

func GetLayerByUserAndId(user *resource.User, rootId string) (*Layer, error) {
    l := &Layer{}
    has, err := models.Engine.Where("creator=?", user.Id).And("root_id=?", rootId).Get(l)
    if err != nil {
        _ = logger.Error("GetLayerByUserAndId err : ", err)
        return nil, InternalServerError(LayerGetError, err.Error())
    }
    if !has {
        _ = logger.Warn("GetLayerByUserAndId: did not find layer info, rootId=%v, userId=%v", rootId, user.Id)
        return nil, InternalServerError(LayerGetError, "没有找到层数据")
    }
    return l, nil
}

func GetLayerVersionByUserAndId(user *resource.User, rootId, version string) (*Layer, error) {
    l := &Layer{}
    has, err := models.Engine.Where("creator=?", user.Id).And("root_id=?", rootId).And("version=?", version).Get(l)
    if err != nil {
        _ = logger.Error("GetLayerByUserAndId err : ", err)
        return nil, InternalServerError(LayerGetError, err.Error())
    }
    if !has {
        _ = logger.Warn("GetLayerByUserAndId: did not find layer info, rootId=%v, userId=%v", rootId, user.Id)
        return nil, InternalServerError(LayerGetError, "没有找到层数据")
    }
    return l, nil
}

// GetLayerCountAll 获取所有的层的数量，包括已经删除的
func GetLayerCountAll(id string) (int64, error) {
    count, err := models.Engine.Unscoped().Where("root_id=?", id).Count(new(Layer))
    if err != nil {
        _ = logger.Error("GetLayerCountAll: get layer count error %v", err)
        return 0, err
    }
    return count, err
}

func GetLayerList(query *LayerListQuery) ([]*Layer, error) {
    layerList := make([]*Layer, 0)
    subSql := fmt.Sprintf("select * from fcs_layer where account_id = '%s' and delete_time is NULL ", query.AccountId)
    if query.LayerName != "" {
        subSql = subSql + fmt.Sprintf("and INSTR(name,'%s') ", query.LayerName)
    }
    subSql = subSql + "order by update_time desc limit 100000"
    sql := fmt.Sprintf("select * from (%s) as l1 group by l1.root_id", subSql)
    // 如果没有分页信息，就查询出全部的
    if query.PageSize != 0 || query.PageNo != 0 {
        sql = sql + fmt.Sprintf(" ORDER BY update_time desc limit %d,%d", query.PageSize*(query.PageNo-1), query.PageSize)
    }
    session := models.Engine.SQL(sql)
    err := session.Find(&layerList)
    if err != nil {
        _ = logger.Error("GetLayerList: get layer list error %v", err)
        return nil, err
    }
    return layerList, nil
}

func GetLayerVersionList(layerId string) ([]*Layer, error) {
    layerList := make([]*Layer, 0)
    err := models.Engine.Where("root_id=?", layerId).Desc("update_time").Find(&layerList)
    if err != nil {
        _ = logger.Error("GetLayerVersionList: get layer list error %v", err)
        return nil, err
    }
    return layerList, nil
}

func GetLayerByVersionIds(uid string, versionIds []string) ([]*Layer, error) {
    layerList := make([]*Layer, 0)
    versionIdStr := make([]string, 0)
    // 为了适配sql语法，给id两边加上引号
    for _, versionId := range versionIds {
        versionIdStr = append(versionIdStr, "\""+versionId+"\"")
    }
    idString := strings.Join(versionIdStr, ",")
    // 按照数组中的id顺序进行排序
    err := models.Engine.Where("creator=?", uid).In("id", versionIds).OrderBy(fmt.Sprintf("FIELD(id, %s)", idString)).Find(&layerList)
    if err != nil {
        _ = logger.Error("GetLayerByVersionIds: get layer list error %v", err)
        return nil, err
    }
    return layerList, nil
}

func GetLayerByRuntime(uid, runtime string) ([]*Layer, error) {
    layerList := make([]*Layer, 0)
    err := models.Engine.Where("creator=?", uid).Where("INSTR(runtimes,?)", runtime).Desc("update_time").Find(&layerList)
    if err != nil {
        _ = logger.Error("GetLayerVersionList: get layer list error %v", err)
        return nil, err
    }
    return layerList, nil
}

func GetLayerListCount(query *LayerListQuery) (int64, error) {
    session := models.Engine.Where("creator=?", query.Creator)
    if query.LayerName != "" {
        session = session.Where("INSTR(name,?)", query.LayerName)
    }
    count, err := session.Distinct("root_id").Count(new(Layer))
    if err != nil {
        _ = logger.Error("GetLayerList: get layer list error %v", err)
        return 0, err
    }
    return count, nil
}

func DeleteLayerVersion(rootId, version string) (int64, error) {
    line, err := models.Engine.Where("root_id=?", rootId).Where("version=?", version).Delete(new(Layer))
    if err != nil {
        _ = logger.Error("DeleteLayerVersion: delete layer version error %v", err)
        return 0, err
    }
    return line, nil
}

func (l Layer) TableName() string {
    return "fcs_layer"
}

func (l *Layer) GetLayerPath() string {
    return fmt.Sprintf("%s/%s/%s/", l.Creator+"-layer", l.RootId, l.Version)
}
